﻿using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Core.ProcessManager.Server;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.UI.Authorization;
using Sinacor.Infra.Core.ProcessManager.Server.Security;
using Sinacor.Process.Bovespa.MensagensAlocacao.Server.ResourceAccess;
using PSE.ProcessManager.Server.Process.Security;
using PSE.ProcessManager.Common.Process;

namespace Sinacor.Process.Bovespa.MensagensAlocacao.Server.ProcessLogic
{
    public class MensagensAlocacao : BaseProcessLogic
    {
        #region Campos

        private ResourceAccess.MensagensAlocacao _raMensagensAlocacao = null;
        private Communication.ControleMovimentoOrdens _communicationControleMovimentoOrdens = null;
        private ProcessEntity.InformacoesMovimento _infoMovimento = null;
        
        #endregion
        
        #region Métodos

        #region Inicializar

        public void Inicializar()
        {
            this._raMensagensAlocacao = new ResourceAccess.MensagensAlocacao();
            this._communicationControleMovimentoOrdens = new Communication.ControleMovimentoOrdens();

            this._infoMovimento = this._communicationControleMovimentoOrdens.ObterInformacoesMovimento(new ProcessEntity.DataMovimento());
        }

        #endregion

        #region EnviarMensagensAlocacao

        /// <summary>
        /// Executa a transmissão de mensagens de alocação para a central depositária
        /// </summary>
        /// <param name="parameter"></param>
        private long EnviarMensagensAlocacao(ProcessEntity.DadosExecucao parameter)
        {            
            ProcessEntity.Resultado resultado = this._raMensagensAlocacao.EnviarMensagensAlocacao(parameter);

            if (resultado.Sucesso == false)
            {
                if (resultado.CodigoErro == -1)
                {
                    throw new BusinessException(109643);
                }
                else
                {
                    this.TratarExcecoes(resultado);
                }
            }
            
            return Convert.ToInt64(resultado.Valor);
        } 

        #endregion

        #region Execute
        /// <summary>
        /// Executa a geração e transmissão de mensagens de alocação para a central depositária
        /// </summary>
        /// <param name="parameter"></param>
        public ProcessEntity.InformacoesProcesso Execute(ProcessEntity.DadosExecucao parameter)
        {
            ProcessEntity.InformacoesProcesso retorno = null;

            if (parameter != null)
            {
                retorno = new ProcessEntity.InformacoesProcesso();

                this.ValidarPermissaoExecucao();
                retorno.QuantidadeAlocacoesGeradas = this.GerarMensagensAlocacao(parameter);
                retorno.QuantidadeAlocacoesEnviadas = this.EnviarMensagensAlocacao(parameter);                
            }
            else
            {
                throw new BusinessException(109589);
            }

            return retorno;
        } 
        #endregion

        #region GerarMensagensAlocacao

        /// <summary>
        /// Executa o processo de geração de alocações
        /// </summary>
        /// <param name="parameter"></param>
        private long GerarMensagensAlocacao(ProcessEntity.DadosExecucao parameter)
        {           
            ProcessEntity.Resultado resultado = this._raMensagensAlocacao.GerarMensagensAlocacao(parameter, this._infoMovimento.DataMovimento);
            
            if (resultado.Sucesso == false)
            {
                if (resultado.CodigoErro == -1)
                {
                    throw new BusinessException(109633);
                }
                else
                {
                    this.TratarExcecoes(resultado);
                }
            }
            
            return Convert.ToInt64(resultado.Valor);
        } 

        #endregion

        #region TratarExcecoes

        /// <summary>
        /// Trata exceções geradas pelo Oracle
        /// </summary>
        /// <param name="resultado"></param>
        private void TratarExcecoes(ProcessEntity.Resultado resultado)
        {
            if (string.IsNullOrEmpty(resultado.Argumentos))
            {
                throw new BusinessException(resultado.CodigoErro.Value);
            }
            else
            {
                throw new BusinessException(resultado.CodigoErro.Value, ErrorMessage.ConvertXmlArgumentsToParameters(resultado.Argumentos));
            }
        } 

        #endregion

        #region ValidarEstadoMovimento

        /// <summary>
        /// Valida se o estado do movimento se encontra aberto
        /// </summary>
        private bool ValidarEstadoMovimento()
        {
            bool isValidaEstadoMovimento = true;            
            
            if (this._infoMovimento != null && this._infoMovimento.EstadoMovimento != ProcessEntity.Enum.TipoMovimento.Abertura)
            {
                isValidaEstadoMovimento = false;
            }

            return isValidaEstadoMovimento;
        } 

        #endregion

        #region ValidarPermissaoExecucao

        /// <summary>
        /// Valida se a execução do processo pode ocorrer
        /// </summary>
        private void ValidarPermissaoExecucao()
        {
            SinacorAuthorizationContext authorizationContext = AuthorizationContext<SinacorAuthorizationContext>.Current;

            if (authorizationContext.CheckUserAccess("ORDM", "ORD"))
            {
                if (!this.ValidarEstadoMovimento())
                {
                    throw new BusinessException(109628);
                }
            }
            else
            {
                throw new BusinessException(109627);
            }
        } 

        #endregion

        #endregion
    }

}